/*******************************************************************************
 * Copyright 2010 MoBrite (A venture of Kinara Systems Private Limited)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.mobrite.domaindroid.activity;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.mobrite.domaindroid.Constants;
import com.mobrite.domaindroid.DomainDroidException;
import com.mobrite.domaindroid.DomainStatus;
import com.mobrite.domaindroid.Preferences;
import com.mobrite.domaindroid.R;
import com.mobrite.domaindroid.db.DomainDroidDbAdapter;
import com.mobrite.domaindroid.db.DomainObject;
import com.mobrite.domaindroid.util.Logger;
import com.mobrite.domaindroid.util.RegistrarHelper;
import com.mobrite.domaindroid.util.UiHelper;
import com.mobrite.domaindroid.util.Util;
import com.mobrite.domaindroid.util.WhoisUtil;
import com.mobrite.domaindroid.whoisparser.WhoisResponseParser;

public class DomainListActivity extends ListActivity  implements OnItemClickListener, AnimationListener, OnClickListener {

	private DomainDroidDbAdapter dbHelper;
	//private Cursor cursor;
	//SimpleCursorAdapter notes;
	
	// Menu Ids
	//static final int MENU_ID_ADD_TO_FAVOURITES 	= 1;
	static final int MENU_ID_DELETE 				= 2;
	static final int MENU_ID_LOOKUP_AGAIN		 	= 3;
	static final int MENU_ID_PREFS			 	= 4;
	static final int MENU_ID_ABOUT			 	= 5;
	static final int MENU_ID_OPEN_IN_BROWSER	 	= 6;
	static final int MENU_ID_REGISTER			 	= 7;

	//UI
	ListView listView;
	
    private int mFirstSelectedItemTop = 0;
    private int mFirstSelectedItemPosition = -1;
    private int mFirstSelectedItemHeight = -1;
	private View mMultiSelectPanel;
	private Button mLookupAgainButton;
	private Button mFavoriteButton;
	private Button mDeleteButton;
	private DomainListAdapter mListAdapter;

	int listType;
	String listSortOrder = DomainDroidDbAdapter.orderBy;
	
	Preferences mPrefs;
	UiHelper uiHelper;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {		
		super.onCreate(savedInstanceState);
				
		setContentView(R.layout.domain_list);
		
		listType = getIntent().getIntExtra(Constants.EXTRA_LIST_TYPE, Constants.LIST_TYPE_AVAILABLE);
		
		mPrefs = new Preferences(this);
		DomainDroidDbAdapter.orderBy = mPrefs.getSortingOption();
		
		TextView empty = (TextView) findViewById(android.R.id.empty);
		
		switch (listType) {
		case Constants.LIST_TYPE_AVAILABLE:
			empty.setText(getResources().getString(R.string.empty_list_available));
			break;

		case Constants.LIST_TYPE_TAKEN:
			empty.setText(getResources().getString(R.string.empty_list_taken));
			break;

		case Constants.LIST_TYPE_FAVORITES:
			empty.setText(getResources().getString(R.string.empty_list_favorites));
			break;

		default:
			break;
		}
		Logger.d("onCreate() - listType = "+listType);

        mMultiSelectPanel = findViewById(R.id.footer_organize);
        mLookupAgainButton = (Button) findViewById(R.id.btn_refresh);
        mFavoriteButton = (Button) findViewById(R.id.btn_multi_favorite);
        mDeleteButton = (Button) findViewById(R.id.btn_multi_delete);
		listView = getListView();

		mLookupAgainButton.setOnClickListener(this);
        mFavoriteButton.setOnClickListener(this);
        mDeleteButton.setOnClickListener(this);

        DomainDroidDbAdapter.orderBy = mPrefs.getSortingOption();
		dbHelper = new DomainDroidDbAdapter(this);
		dbHelper.open();
				
		fillData();
		registerForContextMenu(getListView());
		
		listView.setOnItemClickListener(this);
		listView.setItemsCanFocus(false);

		uiHelper = new UiHelper(this);
	}
	
	@Override
	protected void onDestroy() {
		Logger.d("onDestroy()");

		super.onDestroy();
		mListAdapter.getCursor().close();
		dbHelper.close();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		Logger.d("onResume()");
		String orderBy = mPrefs.getSortingOption();
		if (!listSortOrder.equals(orderBy)) {
			// orderBy was changed by the user, need to reload cursor
			DomainDroidDbAdapter.orderBy = orderBy;
			listSortOrder = orderBy;
			mListAdapter.getCursor().close();
			Cursor cursor = refreshCursor();
			mListAdapter.changeCursor(cursor);
		}
			
		mListAdapter.getCursor().requery();
		InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(getListView().getWindowToken(), 0);
	}
	
	@Override
	protected void onPause() {
		Logger.d("onPause()");
		super.onPause();
	}

	@Override
	protected void onRestart() {
		Logger.d("onRestart()");
		super.onRestart();
	}
	
	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
	}
	
	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
	}
	
	private Cursor refreshCursor() {

		Cursor cursor = null;
		
		switch (listType) {
		case Constants.LIST_TYPE_AVAILABLE:
			cursor = dbHelper.getAvailableDomains();
			break;

		case Constants.LIST_TYPE_TAKEN:
			cursor = dbHelper.getTakenDomains();
			break;

		case Constants.LIST_TYPE_FAVORITES:
			cursor = dbHelper.getFavouriteDomains();
			break;

		default:
			break;
		}
		
		return cursor;
	}
	
	private void fillData() {
        // Get all of the rows from the database and create the item list
		
		Cursor cursor = refreshCursor();
		
        //startManagingCursor(cursor);
		mListAdapter = new DomainListAdapter(this);
		if (cursor!=null) {
			mListAdapter.changeCursor(cursor);
		}
		setListAdapter(mListAdapter);
		
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    	super.onCreateOptionsMenu(menu);
    	
        MenuItem prefsItem = menu.add(0, MENU_ID_PREFS, 0, getResources().getString(
                R.string.menu_prefs));
        prefsItem.setIcon(android.R.drawable.ic_menu_preferences);

        menu.add(0, MENU_ID_ABOUT, 0, getResources().getString(R.string.menu_about)).setIcon(android.R.drawable.ic_menu_help);

        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

    	switch (item.getItemId()) {
		case MENU_ID_PREFS:
			Intent intent = new Intent(this, PreferencesActivity.class);
			startActivity(intent);
			return true;

		case MENU_ID_ABOUT:
			uiHelper.showAboutDialog();
			return true;

		default:
			break;
		}
    	
    	return false;
    }
    
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		//if (listType!=Constants.LIST_TYPE_FAVORITES) menu.add(0, MENU_ID_ADD_TO_FAVOURITES, 0, "Add to Favorites");
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
		DomainListItem itemView = (DomainListItem) info.targetView;
		menu.setHeaderTitle(itemView.getDomainObject().getDomain());
		menu.add(0, MENU_ID_LOOKUP_AGAIN, 0, R.string.menu_recheck);
		if (!itemView.mAvailable) {
			menu.add(0, MENU_ID_OPEN_IN_BROWSER, 0, R.string.menu_openInBrowser).setIntent(new Intent(Intent.ACTION_VIEW,
					Uri.parse("http://"+itemView.domain)));			
		}
		else {			
			menu.add(0, MENU_ID_REGISTER, 0, R.string.menu_register);
		}
		menu.add(0, MENU_ID_DELETE, 0, R.string.menu_delete);
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) {

		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
				.getMenuInfo();
		
        final DomainListItem itemView = (DomainListItem) info.targetView;

		switch (item.getItemId()) {
//		case MENU_ID_ADD_TO_FAVOURITES:
//			mListAdapter.updateFavorite(domainResultListItem, mFavorite)
//			if (dbHelper.setFavorite(info.id, true)) {
//				Toast.makeText(this, "Added to Favorites", Toast.LENGTH_LONG).show();
//			}
//			return true;

		case MENU_ID_LOOKUP_AGAIN:
			mListAdapter.mLookupBusy.add(Long.valueOf(info.id));
			new RefreshStatusTask(itemView.getDomainObject()).execute();
			mListAdapter.getCursor().requery();
			return true;
		
		case MENU_ID_DELETE:
			doDeleteFromContextMenu(itemView.getDomainObject());
			return true;
			
		case MENU_ID_REGISTER:
			uiHelper.showRegistrarList(new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Toast.makeText(DomainListActivity.this, "Selected: "+which, Toast.LENGTH_SHORT).show();
					Intent i = new Intent(Intent.ACTION_VIEW,
							Uri.parse(RegistrarHelper.getRegisterUrlForDomain(which, Util.getDomainWithoutTld(itemView.domain), itemView.tld)));
					startActivity(i);
				}
			});			
			return true;
			
		default:
			return super.onContextItemSelected(item);
		}
	}

    /**
     * Show or hide the panel of multi-select options
     */
    private void showMultiPanel(boolean show) {
    	//Logger.d("showMultiPanel("+show+")");
    	
        if (show && mMultiSelectPanel.getVisibility() != View.VISIBLE) {
            mMultiSelectPanel.setVisibility(View.VISIBLE);
            Animation animation = AnimationUtils.loadAnimation(this, R.anim.footer_appear);
            animation.setAnimationListener(this);
            mMultiSelectPanel.startAnimation(animation);
        } else if (!show && mMultiSelectPanel.getVisibility() != View.GONE) {
            mMultiSelectPanel.setVisibility(View.GONE);
            mMultiSelectPanel.startAnimation(
                        AnimationUtils.loadAnimation(this, R.anim.footer_disappear));
        }
        if (show) {
            updateFooterButtonNames();
        }
    }

    private void updateFooterButtonNames () {
        // Show "set_star_action" when one or more un-starred messages are selected.
        if (testMultiple(mListAdapter.getSelectedDomainObjects().keySet(),
                DomainDroidDbAdapter.KEY_FAVORITE, false)) {
            mFavoriteButton.setText("Set Favorite");
        } else {
            mFavoriteButton.setText("Unset Favorite");
        }
    }

    /**
     * Test selected messages for showing appropriate labels
     * @param selectedSet
     * @param column_id
     * @param defaultflag
     * @return true when the specified flagged message is selected
     */
    private boolean testMultiple(Set<Long> selectedSet, String column_key, boolean defaultflag) {
        Cursor c = mListAdapter.getCursor();
        if (c == null || c.isClosed()) {
            return false;
        }
        c.moveToPosition(-1);
        while (c.moveToNext()) {
            long id = c.getInt(c.getColumnIndex(DomainDroidDbAdapter.KEY_ROWID));
            if (selectedSet.contains(Long.valueOf(id))) {
                if (c.getInt(c.getColumnIndex(column_key)) == (defaultflag? 1 : 0)) {
                    return true;
                }
            }
        }
        return false;
    }

    class DomainListAdapter extends CursorAdapter implements DomainListItemViewCallback {

        Context mContext;
        private LayoutInflater mInflater;
        private Drawable mFavoriteIconOn;
        private Drawable mFavoriteIconOff;
        private Drawable mSelectedIconOn;
        private Drawable mSelectedIconOff;

        Resources resources;
        
        //private HashSet<Long> mChecked = new HashSet<Long>();

        // Id's of domains whose re-lookup is currently in progress (to determine whether to show progressbar in the row)
        private HashSet<Long> mLookupBusy = new HashSet<Long>();
        
        // Container for DomainObjects, used by Refresh task 
        private HashMap<Long, DomainObject> mSelectedDomainObjects = new HashMap<Long, DomainObject>();
        
		public DomainListAdapter(Context context) {
			super(context, null, true);
			mContext = context;			
            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

			resources = context.getResources();
            mFavoriteIconOn = resources.getDrawable(R.drawable.btn_star_big_buttonless_dark_on);
            mFavoriteIconOff = resources.getDrawable(R.drawable.btn_star_big_buttonless_dark_off);
            mSelectedIconOn = resources.getDrawable(R.drawable.btn_check_buttonless_dark_on);
            mSelectedIconOff = resources.getDrawable(R.drawable.btn_check_buttonless_dark_off);
		}

		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			
            DomainListItem itemView = (DomainListItem) view;
            itemView.viewInit(this, true);

            // Load the public fields in the view (for later use)
            itemView.id = cursor.getLong(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_ROWID));
            itemView.domain = cursor.getString(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_DOMAIN));
            itemView.tld = cursor.getString(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_TLD));
            itemView.mFavorite = cursor.getInt(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_FAVORITE))==1;
            itemView.timestamp = Util.getTimeFromDbString(cursor.getString(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_TIMESTAMP)));
            //itemView.status = ;
            itemView.mAvailable = cursor.getInt(cursor.getColumnIndex(DomainDroidDbAdapter.KEY_ISAVAILABLE))==1;
            itemView.mSelected = mSelectedDomainObjects.keySet().contains(Long.valueOf(itemView.id));
            
			//Logger.d("bindView() called: domain = "+itemView.domain);

			TextView domain = (TextView) view.findViewById(R.id.domain);
			TextView status = (TextView) view.findViewById(R.id.status);
			TextView timestamp = (TextView) view.findViewById(R.id.timestamp);

            /*
             * TODO: Show ProgressBar + "Checking..." status if this domain is present in the BUSY set.
             */
        	ProgressBar progress = (ProgressBar) view.findViewById(R.id.ProgressBar01);            
            if (mLookupBusy.contains(Long.valueOf(itemView.id))) {
            	progress.setVisibility(View.VISIBLE);
            	status.setText("Checking...");
    			status.setTextColor(Color.LTGRAY);
            }
            else {
            	progress.setVisibility(View.INVISIBLE);
            	status.setText(itemView.mAvailable ? "AVAILABLE" : "TAKEN");
    			status.setTextColor(itemView.mAvailable ? resources.getColor(R.color.available) : resources.getColor(R.color.taken));
            }

			domain.setText(itemView.domain);
			timestamp.setText(Util.getDateForListDisplay(DomainListActivity.this, itemView.timestamp)+")");
			
			ImageView selectedView = (ImageView) view.findViewById(R.id.selected);
			selectedView.setImageDrawable(itemView.mSelected ? mSelectedIconOn : mSelectedIconOff);

			ImageView favoriteView = (ImageView) view.findViewById(R.id.favorite);
			if (listType!=Constants.LIST_TYPE_FAVORITES) {
	            favoriteView.setImageDrawable(itemView.mFavorite ? mFavoriteIconOn : mFavoriteIconOff);
			}
			else {
				// Favorites List does not show the star icon
				favoriteView.setVisibility(View.INVISIBLE);
			}
		}

		@Override
		public View newView(Context context, Cursor cursor, ViewGroup parent) {
			return mInflater.inflate(R.layout.domain_list_item, parent, false);
		}
    			
		public void updateSelected(DomainListItem itemView,
				boolean newSelected) {
            ImageView selectedView = (ImageView) itemView.findViewById(R.id.selected);
            selectedView.setImageDrawable(newSelected ? mSelectedIconOn : mSelectedIconOff);

            // Set checkbox state in list, and show/hide panel if necessary
            Long id = Long.valueOf(itemView.id);
//            Logger.d("selected = "+newSelected+", id = "+id);
//            Logger.d("before: mChecked.size() = "+mChecked.size());
			//Logger.d("itemView in updateSelected(): "+itemView.toString());
			
            if (newSelected) {
                //mChecked.add(id);
                mSelectedDomainObjects.put(id, itemView.getDomainObject());
            } else {
                //mChecked.remove(id);
                mSelectedDomainObjects.remove(id);
            }

            Logger.d("mSelectedViewItems.size() = "+mSelectedDomainObjects.size());

            if (mSelectedDomainObjects.size() == 1 && newSelected) {
                mFirstSelectedItemPosition = getListView().getPositionForView(itemView);
                mFirstSelectedItemTop = itemView.getBottom();
                mFirstSelectedItemHeight = itemView.getHeight();
            } else {
                mFirstSelectedItemPosition = -1;
            }

            DomainListActivity.this.showMultiPanel(mSelectedDomainObjects.size() > 0);
			
		}

//        public Set<Long> getSelectedSet() {
//            return mChecked;
//        }
        
        public HashMap<Long, DomainObject> getSelectedDomainObjects() {
        	return mSelectedDomainObjects;
        }

		@Override
		public void updateFavorite(DomainListItem domainResultListItem, boolean mFavorite) {
			if (listType==Constants.LIST_TYPE_FAVORITES) return;
			
			ImageView favoriteView = (ImageView) domainResultListItem.findViewById(R.id.favorite);
            favoriteView.setImageDrawable(mFavorite ? mFavoriteIconOn : mFavoriteIconOff);

			if (domainResultListItem.id>=0) {
				dbHelper.setFavorite(domainResultListItem.id, mFavorite);
			}
			else {
				dbHelper.setFavorite(domainResultListItem.domain+"."+domainResultListItem.tld, domainResultListItem.tld, mFavorite);
			}		

			doRequery();
			//getCursor().requery();
			//super.onContentChanged(); //TODO This should be probably be done on a separate thread...

		}

    }
    
    private void updateListPosition () {
        int listViewHeight = getListView().getHeight();
        if (mListAdapter.getSelectedDomainObjects().size() == 1 && mFirstSelectedItemPosition >= 0
                && mFirstSelectedItemPosition < getListView().getCount()
                && listViewHeight < mFirstSelectedItemTop) {
            getListView().setSelectionFromTop(mFirstSelectedItemPosition,
                    listViewHeight - mFirstSelectedItemHeight);
        }
    }

	@Override
	public void onAnimationEnd(Animation animation) {
		updateListPosition();		
	}

	@Override
	public void onAnimationRepeat(Animation animation) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onAnimationStart(Animation animation) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_refresh:
            doMultiLookup(mListAdapter.getSelectedDomainObjects());
            break;
        case R.id.btn_multi_favorite:
            doMultiToggleFavorite(mListAdapter.getSelectedDomainObjects().keySet());
            break;
        case R.id.btn_multi_delete:
            doMultiDelete(mListAdapter.getSelectedDomainObjects().keySet());
            break;
        }
		
	}

    private interface MultiToggleHelper {
        /**
         * Return true if the field of interest is "set".  If one or more are false, then our
         * bulk action will be to "set".  If all are set, our bulk action will be to "clear".
         * @param messageId the message id of the current message
         * @param c the cursor, positioned to the item of interest
         * @return true if the field at this row is "set"
         */
        public boolean getField(long id, Cursor c);

        /**
         * Set or clear the field of interest.  Return true if a change was made.
         * @param messageId the message id of the current message
         * @param c the cursor, positioned to the item of interest
         * @param newValue the new value to be set at this row
         * @return true if a change was actually made
         */
        public boolean setField(long id, Cursor c, boolean newValue);
    }

    /**
     * Toggle multiple fields in a message, using the following logic:  If one or more fields
     * are "clear", then "set" them.  If all fields are "set", then "clear" them all.
     *
     * @param selectedSet the set of messages that are selected
     * @param helper functions to implement the specific getter & setter
     * @return the number of messages that were updated
     */
    private int toggleMultiple(Set<Long> selectedSet, MultiToggleHelper helper) {
        Cursor c = mListAdapter.getCursor();
        boolean anyWereFound = false;
        boolean allWereSet = true;

        c.moveToPosition(-1);
        while (c.moveToNext()) {
            long id = c.getInt(c.getColumnIndex(DomainDroidDbAdapter.KEY_ROWID));
            if (selectedSet.contains(Long.valueOf(id))) {
                anyWereFound = true;
                if (!helper.getField(id, c)) {
                    allWereSet = false;
                    break;
                }
            }
        }

        int numChanged = 0;

        if (anyWereFound) {
            boolean newValue = !allWereSet;
            c.moveToPosition(-1);
            while (c.moveToNext()) {
                long id = c.getInt(c.getColumnIndex(DomainDroidDbAdapter.KEY_ROWID));
                if (selectedSet.contains(Long.valueOf(id))) {
                    if (helper.setField(id, c, newValue)) {
                        ++numChanged;
                    }
                }
            }
        }

        return numChanged;
    }

    private void doDeleteFromContextMenu (DomainObject dobj) {
        dbHelper.deleteDomain(dobj.getRowId());
        Toast.makeText(DomainListActivity.this, dobj.getDomain()+" deleted.", Toast.LENGTH_LONG).show();
        mListAdapter.getSelectedDomainObjects().remove(Long.valueOf(dobj.getRowId()));
        if (mListAdapter.getSelectedDomainObjects().size()==0) {
        	showMultiPanel(false);
        }
        doRequery();
    }
    
	private void doMultiDelete(final Set<Long> selectedSet) {

		String deleteMsg = getResources().getString( selectedSet.size()>1 ? R.string.confirm_delete_dialog_message_plural : R.string.confirm_delete_dialog_message_single);

		AlertDialog.Builder builder = new AlertDialog.Builder(this).
			setTitle(R.string.confirm_delete_dialog_title).
			setMessage(deleteMsg).
			setPositiveButton("Yes", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {

					HashSet<Long> cloneSet = new HashSet<Long>(selectedSet);
			        for (Long id : cloneSet) {
			            dbHelper.deleteDomain(id.longValue());
			        }
			        
			        String toastStr = selectedSet.size() + (selectedSet.size()>1 ? " entries deleted." : " entry deleted.");
			        Toast.makeText(DomainListActivity.this, toastStr, Toast.LENGTH_LONG).show();
			        mListAdapter.getSelectedDomainObjects().clear();
			        showMultiPanel(false);		
				
			        doRequery();
				}
			}).
			setNegativeButton("No", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					
				}
			});
		
		builder.create().show();
			
	}

	private void doMultiToggleFavorite(Set<Long> selectedSet) {
        toggleMultiple(selectedSet, new MultiToggleHelper() {

            public boolean getField(long messageId, Cursor c) {
                return c.getInt(c.getColumnIndex(DomainDroidDbAdapter.KEY_FAVORITE)) != 0;
            }

            public boolean setField(long messageId, Cursor c, boolean newValue) {
                boolean oldValue = getField(messageId, c);
                if (oldValue != newValue) {
                	Logger.d("doMultiToggleFavorite() : newValue = "+newValue);
                	dbHelper.setFavorite(messageId, newValue);
                    //onSetMessageFavorite(messageId, newValue);
                    return true;
                }
                return false;
            }
        });
		
        if (listType==Constants.LIST_TYPE_FAVORITES) {
        	/*
        	 * In favorites list view, removing an item from favorites results in the item disappearing from the list view.
        	 * We need to explicitly clear the selections and remove the footer bar in this case.
        	 */
        	//mListAdapter.mChecked.clear();
        	mListAdapter.mSelectedDomainObjects.clear();
        	showMultiPanel(false);
        }
        
        doRequery();
	}

	private void doMultiLookup(HashMap<Long, DomainObject> hashMap) {

		for (DomainObject item : hashMap.values()) {
			//Logger.d("itemView in lookup loop: "+item.toString());
			mListAdapter.mLookupBusy.add(Long.valueOf(item.getRowId()));
			new RefreshStatusTask(item).execute();
		}
		
		mListAdapter.getCursor().requery();
	}

	/**
	 * Refresh List, update footer button text if necessary
	 */
	private void doRequery() {
		mListAdapter.getCursor().requery();
		updateFooterButtonNames();
	}
	
	/**
	 * Async Task to re-query the status of the selected domains
	 * @author ketan
	 *
	 */
	class RefreshStatusTask extends AsyncTask<Void, Void, Integer> {

		DomainObject domainObject;
		
		public RefreshStatusTask(DomainObject domainObject) {
			this.domainObject = domainObject;
			//Logger.d("itemView in RefreshStatusTask constructor: "+view.toString());
			//domain = itemView.domain;
		}
		
		@Override
		protected void onPreExecute() {
		}
		
		@Override
		protected Integer doInBackground(Void... params) {

			Logger.d("RefreshTask executing: "+domainObject.getDomain());
			
			// TESTING ONLY
//			if (domainObject.getDomain().startsWith("kinara")) {
//				return DomainStatus.AVAILABLE;
//			}
			
			if (!WhoisUtil.WHOIS_SERVERS.containsKey(domainObject.getTld())) return DomainStatus.UNSUPPORTED_TLD;
			try {
				String response = WhoisUtil.getWhoisData(WhoisUtil.WHOIS_SERVERS.getProperty(domainObject.getTld()), domainObject.getDomain());
				//whoisData.put(tld, response);
				//itemView.whoisResponse = response;
				WhoisResponseParser parser = WhoisUtil.getWhoisResponseParserForTld(domainObject.getTld());
				return parser.isAvailable(response, domainObject.getDomain()) ? DomainStatus.AVAILABLE : DomainStatus.UNAVAILABLE;

				//return WhoisUtil.checkAvailability(domain, tld) ? DomainStatus.AVAILABLE : DomainStatus.UNAVAILABLE;
			} catch (DomainDroidException e) {
				return DomainStatus.ERROR;
			}
			
		}

		@Override
		protected void onPostExecute(Integer result) {

			Logger.d("RefreshTask finished: "+domainObject.getDomain());
            
			mListAdapter.mLookupBusy.remove(Long.valueOf(domainObject.getRowId()));
            Date date = new Date();
        	domainObject.setLastCheckedTimestamp(date.getTime());
            
            switch (result.intValue()) {
			case DomainStatus.AVAILABLE:
	            if (domainObject.getAvailable()!=1) { // Domain Status has changed
	            	domainObject.setAvailable(1);
	            	if (listType==Constants.LIST_TYPE_TAKEN) {
		            	//mListAdapter.getSelectedSet().remove(Long.valueOf(domainObject.getRowId()));
		            	mListAdapter.getSelectedDomainObjects().remove(Long.valueOf(domainObject.getRowId()));
		            	Toast.makeText(DomainListActivity.this, domainObject.getDomain()+" is now AVAILABLE!", Toast.LENGTH_LONG).show();
	            	}
	            }
				break;
				
			case DomainStatus.UNAVAILABLE:
	            if (domainObject.getAvailable()==1) { // Domain Status has changed
	            	domainObject.setAvailable(0);
	            	if (listType==Constants.LIST_TYPE_AVAILABLE) {
		            	//mListAdapter.getSelectedSet().remove(Long.valueOf(domainObject.getRowId()));
		            	mListAdapter.getSelectedDomainObjects().remove(Long.valueOf(domainObject.getRowId()));
		            	Toast.makeText(DomainListActivity.this, domainObject.getDomain()+" has been TAKEN", Toast.LENGTH_LONG).show();
	            	}
	            }
				break;
				
			case DomainStatus.ERROR:
				break;
				
			case DomainStatus.UNSUPPORTED_TLD:
				break;

			default:
				break;
			}           
            
        	dbHelper.updateDomain(domainObject.getRowId(), domainObject);

        	if (mListAdapter.getSelectedDomainObjects().size()==0) { // All selected items went out of this view, remove bottom panel
        		showMultiPanel(false);
        		doRequery();
        	}
        	else if (mListAdapter.mLookupBusy.isEmpty()) { // Last refresh task completed. Refresh ListView
				doRequery();
			}

		}
		
		@Override
		public int hashCode() {
			return domainObject.hashCode();
		}
		
		@Override
		public boolean equals(Object o) {
			return domainObject.equals(o);
		}
	}
}
